package com.mysterymall.Common.Config;


import cn.dev33.satoken.exception.NotLoginException;
import com.mysterymall.Common.Comp.HttpStatus;
import com.mysterymall.Common.Utils.CommonException;
import com.mysterymall.Common.Utils.Result;
import com.mysterymall.Common.Utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.List;



/**
 * com.htkj.threedimensionalplatform.utils.GlobalExceptionHandler.
 * 全局异常处理
 * @Author: 黄万兴
 * @Date: 2023/03/23/16:03
 * @Description:
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(NotLoginException.class)
    public Result handlerNotLoginException(NotLoginException nle) {
        // 不同异常返回不同状态码
        String message = "";
        if (nle.getType().equals(NotLoginException.NOT_TOKEN)) {
            message = "未提供有效的Token";
        } else if (nle.getType().equals(NotLoginException.INVALID_TOKEN)) {
            message = "未提供有效的Token";
        } else if (nle.getType().equals(NotLoginException.TOKEN_TIMEOUT)) {
            message = "登录信息已过期，请重新登录";
        } else if (nle.getType().equals(NotLoginException.BE_REPLACED)) {
            message = "您的账户已在另一台设备上登录，如非本人操作，请立即修改密码";
        } else if (nle.getType().equals(NotLoginException.KICK_OUT)) {
            message = "已被系统强制下线";
        } else {
            message = "当前会话未登录";
        }
        // 返回给前端
        return new Result(HttpStatus.UNAUTHORIZED,message);
    }

    /**
     * 处理空指针的异常
     * @param req 请求
     * @param e 异常
     * @return Result
     */
    @ExceptionHandler(value =NullPointerException.class)
    @ResponseBody
    public Result exceptionHandler(HttpServletRequest req, NullPointerException e){
        e.printStackTrace();
        log.error("空指针异常:------------------------------>{}",e.getMessage());
        return new Result(HttpStatus.ERROR,"服务器内部错误");
    }


    /**
     * 自定义异常处理
     * @param req 请求
     * @param e 异常
     * @return Result
     */
    @ExceptionHandler(value = CommonException.class)
    public Result exceptionHandler(HttpServletRequest req, CommonException e){
        log.error("业务异常:------------------------------>{}",e.getMessage());
        return new Result(e.getErrorCode(),e.getMessage());
    }

    /**
     * 字段校验异常处理
     * @param e 异常
     * @return Result
     */
    @ExceptionHandler(BindException.class)
    public Result handleValidationException(BindException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        String messages = StringUtils.join(fieldErrors.stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage).toArray(), ";");
        return  new Result(HttpStatus.BAD_REQUEST,messages);
    }

    /**
     * 字段校验异常处理
     * @param e 异常
     * @return Result
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleValidationException(MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        String messages = StringUtils.join(fieldErrors.stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage).toArray(), ";");
        log.error("validation字段校验异常-------------------->{}",messages);
        return new Result(HttpStatus.BAD_NOT_PASS,messages);
    }

    /**
     * 字段校验异常处理
     * @param e 异常
     * @return Result
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result handleConstraintViolationException(ConstraintViolationException e) {
        // 处理验证异常
        return  new Result(HttpStatus.BAD_REQUEST,"数据格式异常",e.getMessage());
    }

    /**
     * 处理其他异常
     * @param req 请求
     * @param e 异常
     * @return Result
     */
    @ExceptionHandler(value =Exception.class)
    @ResponseBody
    public Result exceptionHandler(HttpServletRequest req, Exception e){
        e.printStackTrace();
        log.error("未知原因异常----------------------------->{}",e.getMessage());
        return new Result(HttpStatus.ERROR,"服务器内部错误");
    }
}
